//
//  DDateAnalysisViewController.swift
//  Drop
//
//  Created by hushaohua on 2018/2/25.
//  Copyright © 2018年 init. All rights reserved.
//

import UIKit
import CoreData

class DDateAnalysisViewController: UITableViewController {

    override init(style: UITableViewStyle) {
        super.init(style: .grouped);
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        self.view.backgroundColor = UIColor.white;
        self.configTableView();
        self.configNavigationItem();
        
        self.requestNewest();
    }
    
    func configNavigationItem() -> Void{
        let button = UIBarButtonItem(customView: self.filterButton());
        self.navigationItem.rightBarButtonItem = button;
        self.navigationItem.titleView = self.titleView();
        self.subTitleLabel.text = DPreferences.defaultPreferences().dateAnalysis.text();
    }
    
    func filterButton() -> UIButton{
        let button = UIButton(frame: CGRect(x:0,y:0,width:44,height:44));
        button.contentHorizontalAlignment = .right;
        button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .light);
        button.setTitle("日期", for: .normal);
        button.setTitleColor(UIColor.darkGray, for: .normal);
        button.addTarget(self, action: #selector(changeDate), for: .touchUpInside);
        return button;
    }
    
    func titleView() -> UIView{
        let view = UIView(frame: CGRect(x:0,y:0,width:200,height:44));
        view.addSubview(self.titleLabel());
        view.addSubview(self.subTitleLabel);
        return view;
    }
    
    func titleLabel() -> UILabel{
        let label:UILabel = UILabel(frame: CGRect(x:0,y:6,width:200,height:24));
        label.autoresizingMask = [.flexibleWidth];
        label.text = "日期统计";
        label.font = UIFont.systemFont(ofSize: 18);
        label.textAlignment = .center;
        label.textColor = UIColor.black;
        return label;
    }
    
    lazy var subTitleLabel:UILabel = {
        var label:UILabel = UILabel(frame: CGRect(x:0,y:30,width:200,height:12));
        label.autoresizingMask = [.flexibleWidth];
        label.text = "今天";
        label.font = UIFont.systemFont(ofSize: 10, weight: .light);
        label.textAlignment = .center;
        label.textColor = UIColor.gray;
        return label;
    }();
    
    @objc func changeDate() -> Void{
        weak var weakSelf = self;
        let controller = DAnalysisDatesViewController();
        controller.defaultPrefItem = DPreferences.defaultPreferences().dateAnalysis;
        controller.doneClosure = { pref in
            DPreferences.defaultPreferences().dateAnalysis = pref;
            weakSelf?.subTitleLabel.text = pref.text();
            self.requestNewest();
        };
        controller.hidesBottomBarWhenPushed = true;
        let back = UIBarButtonItem(title: "", style: .plain, target: self, action: nil);
        self.navigationItem.backBarButtonItem = back;
        self.navigationController?.pushViewController(controller, animated: true);
    }
    
    lazy var headerView:DDateAnalysisHeaderView = {
        var view = DDateAnalysisHeaderView(frame: CGRect(x:0,y:-52,width:self.view.bounds.size.width,height:52))
        view.chartTypeChangedClosure = {chartType in
            self.tableView.reloadData();
        };
        return view;
    }();
    
    override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        var insets = self.tableView.contentInset;
        if (insets.top > 0){
            if (scrollView.contentOffset.y > -insets.top - self.navigationController!.navigationBar.bounds.size.height + 12){
                insets.top = 0;
            }
        }else{
            if (scrollView.contentOffset.y < -52){
                insets.top = 52;
            }
        }
        self.tableView.contentInset = insets;
    }
    
    func configTableView() -> Void{
        self.tableView.addSubview(self.headerView);
        self.tableView.tableFooterView = UIView();
        self.tableView.contentInset = UIEdgeInsets(top:0,left:0,bottom:84,right:0);
        self.tableView.rowHeight = 44;
        self.tableView.register(DAnalysisTagTableViewCell.self, forCellReuseIdentifier: "Cell");
        self.tableView.register(DDateAnalysisSectionDateView.self, forHeaderFooterViewReuseIdentifier: "Header");
        self.tableView.register(DDateAnalysisChartFooterView.self, forHeaderFooterViewReuseIdentifier: DDateAnalysisChartFooterView.pieReuseId);
        self.tableView.register(DDateAnalysisChartFooterView.self, forHeaderFooterViewReuseIdentifier: DDateAnalysisChartFooterView.barReuseId);
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    var weekdayTitles:[String] = ["", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
    
    var analysisItems:[DDateTagAnalysisItem] = [DDateTagAnalysisItem]();
    func requestNewest() -> Void{
        self.configTagsRequest();
        do{
            let tags = try HStoreManager.defaultManger().context.fetch(self.tagsRequest);
            self.analysisItems.removeAll();
            let analysis = DPreferences.defaultPreferences().dateAnalysis;
            for dict in tags {
                let interval:Int64 = dict.object(forKey: "intervals") as! Int64;
                let tag:DTagAnalysisItem = DTagAnalysisItem();
                tag.duration = interval;
                tag.count = dict.object(forKey: "count") as! Int32;
                tag.tagName = dict.object(forKey: "tag.name") as! String;
                tag.tagID = dict.object(forKey: "tag") as? NSManagedObjectID;
                var sectionTitle:String? = nil;
                var beginEndDates:(begin:Date, end:Date)? = nil;
                switch analysis.interval {
                case .day:
                    let year = dict.object(forKey: "year") as! Int32;
                    let month = dict.object(forKey: "month") as! Int16;
                    let day = dict.object(forKey: "day") as! Int16;
                    let weekday = dict.object(forKey: "weekday") as! Int;
                    beginEndDates = Date.dayBeginToEndDates(Int(year), month: Int(month), day: Int(day));
                    sectionTitle = "\(year)-\(month)-\(day) \(self.weekdayTitles[weekday])";
                case .week:
                    let year = dict.object(forKey: "yearForWeek") as! Int32;
                    let week = dict.object(forKey: "weekOfYear") as! Int16;
                    beginEndDates = Date.weekBeginToEndDates(Int(week), yearForWeek: Int(year));
                    sectionTitle = "\(beginEndDates!.begin.defaultDateString())->\(beginEndDates!.end.defaultDateString())";
                case .month:
                    let year = dict.object(forKey: "year") as! Int32;
                    let month = dict.object(forKey: "month") as! Int16;
                    beginEndDates = Date.monthBeginToEndDates(Int(year), month: Int(month));
                    sectionTitle = "\(year)年\(month)月";
                }
                tag.beginDate = beginEndDates?.begin;
                tag.endDate = beginEndDates?.end;
                
                let pieChart:HPieChartItem = HPieChartItem();
                let barChart:HBarChartItem = HBarChartItem();
                pieChart.key = tag.tagName;
                pieChart.value = tag.duration;
                pieChart.valueString = tag.durationString();
                barChart.key = tag.tagName;
                barChart.value = tag.duration;
                barChart.valueString = tag.durationString();
                let analysis = self.analysisItems.last;
                if (analysis == nil || analysis!.dateString != sectionTitle!){
                    let item = DDateTagAnalysisItem();
                    item.dateString = sectionTitle!;
                    item.tagItems = [DTagAnalysisItem]();
                    item.pieCharts = [HPieChartItem]();
                    item.barCharts = [HBarChartItem]();
                    item.tagItems?.append(tag);
                    item.pieCharts?.append(pieChart);
                    item.barCharts?.append(barChart);
                    self.analysisItems.append(item);
                }else{
                    analysis!.tagItems?.append(tag);
                    analysis!.pieCharts?.append(pieChart);
                    analysis!.barCharts?.append(barChart);
                }
            }
            for analysis in self.analysisItems {
                analysis.tagItems!.sort(by: { (item1, item2) -> Bool in
                    return item1.duration > item2.duration ? true : false;
                });
                analysis.pieCharts!.sort(by: { (item1, item2) -> Bool in
                    return item1.value > item2.value ? true : false;
                });
                analysis.barCharts!.sort(by: { (item1, item2) -> Bool in
                    return item1.value > item2.value ? true : false;
                });
            }
            self.tableView.reloadData();
        }catch{
            let nserror = error as NSError
            fatalError("tags controller fetch error \(nserror), \(nserror.userInfo)")
        }
    }
    
    func tagsRequestExpressions() -> (interval:NSExpressionDescription, count:NSExpressionDescription){
        let beginDateExp = NSExpression(forKeyPath: "begin");
        let endDateExp = NSExpression(forKeyPath: "end");
        let beginSumExpression = NSExpression(forFunction: "sum:", arguments: [beginDateExp]);
        let endSumExpression = NSExpression(forFunction: "sum:", arguments: [endDateExp]);
        let countExpression = NSExpression(forFunction: "count:", arguments:[endDateExp]);
        let intervalExp = NSExpression(forFunction: "from:subtract:", arguments: [endSumExpression, beginSumExpression]);
        
        let intervalExpDesc = NSExpressionDescription();
        intervalExpDesc.name = "intervals";
        intervalExpDesc.expression = intervalExp;
        intervalExpDesc.expressionResultType = .integer64AttributeType;
        
        let countExpDesc = NSExpressionDescription();
        countExpDesc.name = "count";
        countExpDesc.expression = countExpression;
        countExpDesc.expressionResultType = .integer32AttributeType;
        
        return (intervalExpDesc, countExpDesc);
    }
    
    func configTagsRequest() -> Void{
        let expressions = self.tagsRequestExpressions();
        let analysis = DPreferences.defaultPreferences().dateAnalysis;
        switch analysis.interval {
        case .day:
            self.tagsRequest.propertiesToFetch = ["year", "month", "day", "tag", expressions.interval, expressions.count, "tag.name", "weekday"];
            self.tagsRequest.propertiesToGroupBy = ["year", "month", "day", "weekday", "tag", "tag.name"];
            self.tagsRequest.sortDescriptors = [
                NSSortDescriptor(key: "year", ascending: false),
                NSSortDescriptor(key: "month", ascending: false),
                NSSortDescriptor(key: "day", ascending: false)
            ];
        case .month:
            self.tagsRequest.propertiesToFetch = ["year", "month", "tag", expressions.interval, expressions.count, "tag.name"];
            self.tagsRequest.propertiesToGroupBy = ["year", "month", "tag", "tag.name"];
            self.tagsRequest.sortDescriptors = [
                NSSortDescriptor(key: "year", ascending: false),
                NSSortDescriptor(key: "month", ascending: false)
            ];
        case .week:
            self.tagsRequest.propertiesToFetch = ["yearForWeek", "weekOfYear", "tag", expressions.interval, expressions.count, "tag.name"];
            self.tagsRequest.propertiesToGroupBy = ["yearForWeek", "weekOfYear", "tag", "tag.name"];
            self.tagsRequest.sortDescriptors = [
                NSSortDescriptor(key: "yearForWeek", ascending: false),
                NSSortDescriptor(key: "weekOfYear", ascending: false)
            ];
        }
        var predicates = [NSPredicate]();
        let basePredicate = NSPredicate(format: "tag != nil");
        predicates.append(basePredicate);
        if (analysis.datePredicate != nil){
            predicates.append(analysis.datePredicate!);
        }
        let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates);
        self.tagsRequest.predicate = predicate;
    }
    
    //MARK:- NSFetchedResultsController
    lazy var tagsRequest:NSFetchRequest<NSDictionary> = {
        let expressions = self.tagsRequestExpressions();
        let request:NSFetchRequest<NSDictionary> = NSFetchRequest(entityName: "Drop");
        request.resultType = .dictionaryResultType;
        request.returnsDistinctResults = true;
        request.includesSubentities = false;
        return request;
    }();
    
    //MARK:- tableView
    override func numberOfSections(in tableView: UITableView) -> Int {
        return self.analysisItems.count;
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch self.headerView.chartType {
        case .text:
            return self.analysisItems[section].tagItems!.count;
        default:
            return 0;
        }
    }
    
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 32;
    }
    
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view:DDateAnalysisSectionDateView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "Header") as! DDateAnalysisSectionDateView;
        view.contentView.backgroundColor = UIColor(white:0.96,alpha:1);
        view.dateLabel.text = self.analysisItems[section].dateString;
        return view;
    }
    
    override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        switch self.headerView.chartType {
        case .text:
            return 0;
        case .bar:
            return 100;
        case .pie:
            return 120;
        }
    }
    
    override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        var reuseId = DDateAnalysisChartFooterView.pieReuseId;
        if (self.headerView.chartType == .bar){
            reuseId = DDateAnalysisChartFooterView.barReuseId;
        }
        let view:DDateAnalysisChartFooterView = tableView.dequeueReusableHeaderFooterView(withIdentifier: reuseId) as! DDateAnalysisChartFooterView;
        let item:DDateTagAnalysisItem = self.analysisItems[section];
        switch self.headerView.chartType {
        case .pie:
            view.setPieCharts(item.pieCharts!);
        case .bar:
            view.setBarCharts(item.barCharts!);
        default:
            break;
        }
        
        return view;
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell:DAnalysisTagTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! DAnalysisTagTableViewCell;
        let item:DTagAnalysisItem = self.analysisItems[indexPath.section].tagItems![indexPath.row];
        
        cell.tagLabel.text = item.tagName;
        cell.timeLabel.text = item.durationString();
        cell.accessoryType = .disclosureIndicator;
        return cell;
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true);
        let item:DTagAnalysisItem = self.analysisItems[indexPath.section].tagItems![indexPath.row];
        let controller = DTagDropViewController();
        controller.beginDate = item.beginDate;
        controller.endDate = item.endDate;
        controller.tag = HStoreManager.defaultManger().context.object(with: item.tagID!) as? Tag;
        self.navigationController?.pushViewController(controller, animated: true);
    }

}
